package jp.tonosama.komoki.SimpleGolfScorer2.main;

import java.io.Serializable;
import jp.tonosama.komoki.SimpleGolfScorer2.R;
import jp.tonosama.komoki.SimpleGolfScorer2.Util;
import jp.tonosama.komoki.SimpleGolfScorer2.data.GolfScoreData;
import jp.tonosama.komoki.SimpleGolfScorer2.viewer.ViewerUtil;
import jp.tonosama.komoki.wheel.widget.OnWheelChangedListener;
import jp.tonosama.komoki.wheel.widget.WheelView;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 * @author Komoki
 */
public class MainGolfScorer extends Activity implements AnimationListener {

    /** Bundle */
    private Bundle mIcicle;
    /** 最大プレイヤー人数 */
    public static final int MAX_PLAYER_NUM = 4;
    /**  */
    private ImageView mPrevArrw;
    /**  */
    private ViewGroup mFooterArea;
    /**  */
    private ImageView mDragImag;
    /**  */
    private ImageView mNextArrw;
    /**  */
    private Spinner mParSpinner;
    /**  */
    private Button mViewerButton;
    /**  */
    private Button mGraphButton;
    /**  */
    private boolean mSpinChangeFlg = false;
    /**  */
    private boolean mIsArrwFocus = false;
    /**  */
    private ImageView mCurrentPosImg;
    /** パットスコア用レーティング部品 */
    private RatingBar mRatingBar;
    /**  */
    private boolean mRatingChangeFlg = false;
    /** アンロックボタン */
    private ImageButton mUnlockBtn;
    /**  */
    private boolean mIsCheckFlg = true;
    /**  */
    private boolean mIsCheckShown = false;
    /**  */
    private GolfScoreData mScoreData;
    /**  */
    private DragUi mDragUi = new DragUi();

    @Override
    public void onCreate(final Bundle icicle) {
        super.onCreate(icicle);
        this.mIcicle = icicle;
        setContentView(MainRes.MAIN_LAYOUT_RES_ID);
        Serializable data = getIntent().getSerializableExtra(GolfScoreData.EXTRAS_SEND_SCORE_DATA);
        if (data == null || !(data instanceof GolfScoreData)) {
            return;
        }
        mScoreData = (GolfScoreData) data;
        int savedNumber = getIntent().getExtras().getInt("SAVED_NUMBER");
        mScoreData.setSaveNum(savedNumber);
        // Preferences からデータを取得
        onLoadResult();
        // TextView に情報をセット;
        ((TextView) findViewById(R.id.hole_title)).setText(mScoreData.getHoleTitle());
        // ParSpinnerのセット
        mParSpinner = MainRes.initParSpinner(this);
        // RatingBar のセット
        mRatingBar = (RatingBar) findViewById(R.id.mypat_ratingbar);
        // UnlockBtn のセット
        mUnlockBtn = (ImageButton) findViewById(R.id.unlock_btn);
        // 人名のセット
        TextView[] personNameTextViews = MainRes.getPersonNameTextViews(this);
        for (int i = 0; i < personNameTextViews.length; i++) {
            personNameTextViews[i].setText(mScoreData.getNames()[i]);
        }
        mPrevArrw = (ImageView) findViewById(R.id.arrow_upside);
        //NextAreaの取得
        mFooterArea = (ViewGroup) findViewById(R.id.next_hole_area);
        mDragImag = (ImageView) findViewById(R.id.next_hole_name);
        mNextArrw = (ImageView) findViewById(R.id.arrow_downside);
        mCurrentPosImg = (ImageView) findViewById(R.id.current_player_location);
        //drumPickerを初期化
        MainRes.initDrumPicker(this);
        // エディタのリフレッシュ
        refreshEditor(mScoreData, 0);
        mSpinChangeFlg = false;
        // 
        setupUiAction();
    }

    /**
     * setupUiAction
     */
    private void setupUiAction() {

        // Spinner changed listener
        setSpinnerSelectAction(mParSpinner);
        // Wheel changed listener
        setDrumPickerChangeAction();
        // RatingBar changed listener
        setRatingBarChangeAction(mRatingBar);
        // UnlockButton クリック動作
        setUnLockButtonAction(mUnlockBtn, mScoreData);
        // Viewer ボタンクリック動作
        setViewerButtonAction();
        // フッターエリアをタッチ&ドラッグ動作
        setFooterAreaAction();
        // 前へ/次へボタンクリック時の動作
        setArrowButtonAction();
        // 戻るボタンクリック時の動作
        setExitButtonAction();
    }

    /**
     * setExitButtonAction
     */
    private void setExitButtonAction() {

        findViewById(R.id.main_exit_button).setOnClickListener(new View.OnClickListener() {

            public void onClick(final View v) {
                finish();
            }
        });
    }

    /**
     * setArrowButtonAction
     */
    @SuppressLint("ClickableViewAccessibility")
    private void setArrowButtonAction() {

        // 前のホールへ の矢印ボタンクリック
        mPrevArrw.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(final View v, final MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    return onArrowButtonClick(mPrevArrw);
                }
                return true;
            }
        });
        // 次のホールへ の矢印ボタン
        mNextArrw.setOnTouchListener(new View.OnTouchListener() {

            @SuppressLint("ClickableViewAccessibility")
            public boolean onTouch(final View v, final MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    return onArrowButtonClick(mNextArrw);
                }
                return true;
            }
        });
    }

    /**
     * @param view ImageView
     * @return true: false:
     */
    private boolean onArrowButtonClick(final ImageView view) {

        int resId = MainRes.PREV_ARROW_PRESSED_RES_ID;
        int moveX = findViewById(MainRes.DRUM_PICKER_AREA_RES_ID).getWidth() + 10;
        int moveSlot = -1;
        boolean isNext = view.equals(mNextArrw);
        if (isNext) {
            resId = MainRes.NEXT_ARROW_PRESSED_RES_ID;
            moveX = -findViewById(MainRes.DRUM_PICKER_AREA_RES_ID).getWidth() - 10;
            moveSlot = 1;
        }
        view.setImageResource(resId);
        if (mDragUi.isAnimating()) {
            return false;
        }
        // アニメーション対応
        // (右から中心,中心から右方向,下から中心,中心から下方向)
        View drumPickerArea = findViewById(MainRes.DRUM_PICKER_AREA_RES_ID);
        TranslateAnimation trans = new TranslateAnimation(0, moveX, 0, 0);
        trans.setDuration(200);
        trans.setInterpolator(new DecelerateInterpolator());
        AnimationSet set = new AnimationSet(true);
        set.addAnimation(trans);
        set.setAnimationListener(this);
        mDragUi.setIsNextAnim(isNext);
        mDragUi.setMoveValue(moveSlot);
        mDragUi.setIsAnimating(true);
        drumPickerArea.startAnimation(set);
        return true;
    }

    public boolean onCreateOptionsMenu(final Menu menu) {
        boolean res = super.onCreateOptionsMenu(menu);
        MenuItem menu2 = menu.add(0, Menu.FIRST + 1, Menu.NONE,
                getResources().getString(R.string.menu_delete));
        menu2.setIcon(R.drawable.ic_menu_delete);
        MenuItem menu3 = menu.add(0, Menu.FIRST + 2, Menu.NONE,
                getResources().getString(R.string.menu_setting));
        menu3.setIcon(R.drawable.imane_button_setting);
        return res;
    }

    public boolean onOptionsItemSelected(final MenuItem item) {
        return MainMenuManager.onOptionsItemSelected(item, this, mScoreData);
    }

    public boolean refreshEditor(final GolfScoreData sData, final int holeMove) {

        final int oldCurrentHole = sData.getCurrentHole();
        sData.setCurrentHole((sData.getCurrentHole() + holeMove) % Util.TOTAL_HOLE_COUNT);
        if (sData.getCurrentHole() == 0) {
            sData.setCurrentHole(Util.TOTAL_HOLE_COUNT);
        }
        // ホール移動時、数値入力済みの場合に移動元ホールをロックする対応
        final WheelView[] drum = MainRes.getDrumPicker(MainGolfScorer.this);
        if (holeMove != 0
                && (drum[0].getCurrentItem() != 0 || sData.getNames()[0].trim().length() < 1)
                && (drum[1].getCurrentItem() != 0 || sData.getNames()[1].trim().length() < 1)
                && (drum[2].getCurrentItem() != 0 || sData.getNames()[2].trim().length() < 1)
                && (drum[3].getCurrentItem() != 0 || sData.getNames()[3].trim().length() < 1)) {
            if (!sData.getEachHoleLocked()[oldCurrentHole - 1]) {
                sData.getEachHoleLocked()[oldCurrentHole - 1] = true;
            }
        }
        // 未入力のホールがあった時に警告する対応
        if (holeMove != 0) {
            mIsCheckFlg = false;
            mIsCheckShown = false;
        }
        // ドラムをロックする対応
        for (int i = 0; i < drum.length; i++) {
            drum[i].setIsWheelLocked(sData.getEachHoleLocked()[sData.getCurrentHole() - 1]);
        }
        // Rating の更新
        refreshEditorRating(sData, holeMove);
        // 
        refreshDragAndDrum(sData, drum);
        //
        refreshSpinner(sData);

        refreshPicker();
        return true;
    }

    /**
     * @param sData GolfScoreData
     * @param holeMove int
     */
    private void refreshEditorRating(final GolfScoreData sData, final int holeMove) {

        // ParSpinner 変更時に反映させる対応の不具合対応
        // 前後ホールでパー値が違うときにの変更通知を無効に
        int nextPat = sData.getAbsolutePatting()[0][sData.getCurrentHole() - 1];
        int prevPat = (int) mRatingBar.getRating();
        if (prevPat == nextPat) {
            mRatingChangeFlg = true;
        }
        if (prevPat != nextPat) {
            mRatingChangeFlg = false;
        }
        // RatingBar のカレント数値エリアに値をセット
        mRatingBar.setIsIndicator(false);
        mRatingBar.setRating(sData.getAbsolutePatting()[0][sData.getCurrentHole() - 1]);
        ImageView iv = (ImageView) findViewById(R.id.my_pat_img);
        iv.setImageResource(MainRes.MY_PAT_IMG_RES_IDS[sData.getAbsolutePatting()[0][sData
                .getCurrentHole() - 1]]);
        // RatingBarをロックする対応
        mRatingBar.setIsIndicator(sData.getEachHoleLocked()[sData.getCurrentHole() - 1]);
        // ロック/アンロックボタンを表示する対応
        if (sData.getEachHoleLocked()[sData.getCurrentHole() - 1]) {
            mUnlockBtn.setImageResource(R.drawable.ic_menu_lock);
            mRatingBar.setBackgroundColor(0x66000000);
        } else {
            mUnlockBtn.setImageResource(R.drawable.ic_menu_unlock);
            mRatingBar.setBackgroundColor(0x00000000);
        }
    }

    /**
     * @param sData GolfScoreData
     * @param drum WheelView[]
     */
    private void refreshDragAndDrum(final GolfScoreData sData, final WheelView[] drum) {
        // ホール名と矢印のセット
        mDragImag.setVisibility(View.VISIBLE);
        mCurrentPosImg.setVisibility(View.GONE);
        if (sData.getIs18Hround()) {
            ((ImageView) findViewById(R.id.golf_hole_icon))
                    .setImageResource(R.drawable.golf_hole_icon);
            MainRes.getHoleTitleTextView(MainGolfScorer.this).setBackgroundResource(
                    MainRes.HOLE_NUMBER_IMG_RES_IDS[sData.getCurrentHole() - 1]);
        } else {
            if (sData.getCurrentHole() < 10) {
                ((ImageView) findViewById(R.id.golf_hole_icon))
                        .setImageResource(R.drawable.golf_hole_icon_out);
                MainRes.getHoleTitleTextView(MainGolfScorer.this).setBackgroundResource(
                        MainRes.HOLE_NUMBER_IMG_RES_IDS[sData.getCurrentHole() - 1]);
            } else {
                ((ImageView) findViewById(R.id.golf_hole_icon))
                        .setImageResource(R.drawable.golf_hole_icon_in);
                MainRes.getHoleTitleTextView(MainGolfScorer.this).setBackgroundResource(
                        MainRes.HOLE_NUMBER_IMG_RES_IDS[sData.getCurrentHole() - 10]);
            }
        }
        if (!mIsArrwFocus) {
            mPrevArrw.setImageResource(R.drawable.arrow_leftside);
        }
        if (!mIsArrwFocus) {
            mNextArrw.setImageResource(R.drawable.arrow_rightside);
        }
        // 現在ホール位置を表示する対応
        mDragImag.setImageResource(MainRes.CURRENT_HOLE_IMG_RES_IDS[sData.getCurrentHole() - 1]);
        // いない人の Picker を消す対応
        removeInvisiPersonDrum(drum, sData);
        // drumPicker のカレント数値エリアに値をセット
        for (int i = 0; i < drum.length; i++) {
            drum[i].setCurrentItem(sData.getAbsoluteScore(i)[sData.getCurrentHole() - 1]);
        }
    }

    /**
     * @param sData GolfScoreData
     */
    private void refreshSpinner(final GolfScoreData sData) {

        // ParSpinner 変更時に反映させる対応の不具合対応
        // 前後ホールでパー値が違うときにの変更通知を無効に
        int nextPar = sData.getEachHolePar()[sData.getCurrentHole() - 1]
                - MainRes.MINIMUM_PAR_COUNT;
        int prevPar = mParSpinner.getSelectedItemPosition();
        if (prevPar == nextPar) {
            mSpinChangeFlg = true;
        }
        if (prevPar != nextPar) {
            mSpinChangeFlg = false;
        }
        mParSpinner.setSelection(nextPar);
    }

    /**
     * @param drum WheelView[]
     * @param sData GolfScoreData
     */
    private void removeInvisiPersonDrum(final WheelView[] drum, final GolfScoreData sData) {
        TextView[] personNameTextViews = MainRes.getPersonNameTextViews(this);
        TextView[] personScoreTextViews = MainRes.getPersonScoreTextViews(this);
        for (int i = 0; i < drum.length; i++) {
            if (sData.getNames()[i].trim().length() == 0) {
                personNameTextViews[i].setVisibility(View.GONE);
                drum[i].setVisibility(View.GONE);
                personScoreTextViews[i].setVisibility(View.GONE);
            }
        }
    }

    public void refreshPicker() {
        // トータルスコアを表示
        TextView[] personScoreTextViews = MainRes.getPersonScoreTextViews(this);
        for (int i = 0; i < personScoreTextViews.length; i++) {
            personScoreTextViews[i].setText(String.valueOf(mScoreData.getTotalScore()[i]));
        }
    }

    public void onLoadResult() {
        mScoreData = Util.loadScoreDataFromPref(this, mScoreData.getSaveNum());
        if (mScoreData.getHoleTitle().equals("")) {
            finish();
            return;
        }
    }

    /**
     * @param scoreData GolfScoreData
     */
    private void onSaveResult(final GolfScoreData scoreData) {

        // 現在の状態を保持
        scoreData.setHoleTitle(((TextView) findViewById(R.id.hole_title)).getText().toString());
        scoreData.getEachHolePar()[scoreData.getCurrentHole() - 1] = mParSpinner
                .getSelectedItemPosition() + MainRes.MINIMUM_PAR_COUNT;
        final WheelView[] drumPickers = MainRes.getDrumPicker(this);
        for (int i = 0; i < drumPickers.length; i++) {
            scoreData.getAbsoluteScore(i)[scoreData.getCurrentHole() - 1] = drumPickers[i]
                    .getCurrentItem();
        }
        scoreData.getAbsolutePatting()[0][scoreData.getCurrentHole() - 1] = (int) mRatingBar
                .getRating();

        // プリファレンスに保存
        Util.saveScoreData(this, scoreData);
    }

    public void onConfigurationChanged(final Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        onSaveResult(mScoreData);
        onCreate(mIcicle);
    }

    public void onStart() {
        super.onStart();
        onCreate(this.mIcicle);
    }

    public boolean onKeyDown(final int keyCode, final KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {

            onSaveResult(mScoreData);
            finish();
            return true;
        }
        return false;
    }

    /**
     * onAnimationEndPrev
     * 
     * @param view View
     * @param isNext boolean
     */
    private void onAnimationEndMain(final View view, final boolean isNext) {

        refreshEditor(mScoreData, mDragUi.getMoveValue());
        onSaveResult(mScoreData);

        mDragUi.setCurrentX(DragUi.DEFAULT_X);
        view.layout(DragUi.DEFAULT_X, 0, DragUi.DEFAULT_X + view.getWidth(), 0 + view.getHeight());

        // アニメーション対応
        // (右から中心,中心から右方向,下から中心,中心から下方向)
        int transVal = -400;
        if (isNext) {
            transVal = 400;
        }
        TranslateAnimation trans = new TranslateAnimation(transVal, 0, 0, 0);
        AlphaAnimation alpha = new AlphaAnimation(0, 1);

        trans.setDuration(150);
        alpha.setDuration(150);

        trans.setInterpolator(new DecelerateInterpolator());
        alpha.setInterpolator(new AccelerateInterpolator());

        AnimationSet set = new AnimationSet(true);
        set.addAnimation(trans);
        set.addAnimation(alpha);

        view.startAnimation(set);
    }

    public void onAnimationEnd(final Animation animation) {

        View drumPickerArea = findViewById(MainRes.DRUM_PICKER_AREA_RES_ID);
        onAnimationEndMain(drumPickerArea, mDragUi.isNextAnim());
        mDragUi.setIsAnimating(false);
        return;
    }

    public void onAnimationRepeat(final Animation animation) {
        //
    }

    public void onAnimationStart(final Animation animation) {
        //
    }

    /**
     * setDrumPickerChangeAction
     */
    private void setDrumPickerChangeAction() {

        for (int i = 0; i < MainRes.getDrumPicker(this).length; i++) {
            MainRes.getDrumPicker(this)[i].addChangingListener(new OnWheelChangedListener() {

                public void onChanged(final WheelView wheel, final int oldVal, final int newVal) {
                    // 未入力のホールがあった時に警告する対応 -> S
                    if (mScoreData.getCurrentHole() > 1
                            && !(mScoreData.getEachHoleLocked()[mScoreData.getCurrentHole() - 2])) {
                        if (mIsCheckFlg && !mIsCheckShown) {

                            Resources res = getResources();
                            AlertDialog.Builder dialog = new AlertDialog.Builder(
                                    MainGolfScorer.this);
                            dialog.setTitle(res.getString(R.string.dlg_chenk_uniput_title));
                            dialog.setMessage(res.getString(R.string.dlg_chenk_uniput_alert));
                            dialog.setPositiveButton(android.R.string.ok, null);
                            dialog.create().show();
                            mIsCheckShown = true;

                        } else {
                            mIsCheckFlg = true;
                        }
                    }
                    // 未入力のホールがあった時に警告する対応 -> E
                    onSaveResult(mScoreData);
                    refreshPicker();
                }
            });
        }
    }

    /**
     * @param spinner Spinner
     */
    private void setSpinnerSelectAction(final Spinner spinner) {

        // ParSpinner 変更時の動作
        // ⇒ 選択されている項目を選択してもイベント無い
        // ⇒ 前後ホールに移動してパー値を更新すると、イベント来てしまう
        // ⇒ 色々と問題あり
        spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

            public void onItemSelected(final AdapterView<?> parent, final View view,
                    final int position, final long id) {
                if (!mSpinChangeFlg) {
                    mSpinChangeFlg = true;
                } else {
                    onSaveResult(mScoreData);
                }
            }

            public void onNothingSelected(final AdapterView<?> arg0) {
                Toast.makeText(MainGolfScorer.this,
                        getResources().getString(R.string.toast_nothing_is_selected),
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * setViewerButtonAction
     */
    private void setViewerButtonAction() {

        // View Button クリック動作
        mViewerButton = (Button) findViewById(R.id.viewButton);
        mViewerButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(final View v) {

                onSaveResult(mScoreData);
                ViewerUtil.startTableActivity(MainGolfScorer.this, mScoreData);
            }
        });
        // Graph Buton クリック動作
        mGraphButton = (Button) findViewById(R.id.graphviewButton);
        mGraphButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(final View v) {

                onSaveResult(mScoreData);
                ViewerUtil.startGraphActivty(MainGolfScorer.this, mScoreData);
            }
        });
    }

    /**
     * setFooterAreaAction
     */
    private void setFooterAreaAction() {
        mDragUi.setFooterAreaAction(this, mScoreData, mFooterArea, mPrevArrw, mNextArrw, mDragImag,
                mCurrentPosImg);
    }

    /**
     * @param ratingBar RatingBar
     */
    private void setRatingBarChangeAction(final RatingBar ratingBar) {

        ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {

            public void onRatingChanged(final RatingBar ratingBar, final float rating,
                    final boolean fromUser) {
                if (!mRatingChangeFlg) {
                    mRatingChangeFlg = true;
                } else {
                    ImageView iv = (ImageView) findViewById(R.id.my_pat_img);
                    iv.setImageResource(MainRes.MY_PAT_IMG_RES_IDS[(int) rating]);
                    onSaveResult(mScoreData);
                }
            }
        });
    }

    /**
     * @param button View
     * @param scoreData GolfScoreData
     */
    private void setUnLockButtonAction(final View button, final GolfScoreData scoreData) {

        button.setOnClickListener(new View.OnClickListener() {

            public void onClick(final View v) {
                scoreData.getEachHoleLocked()[scoreData.getCurrentHole() - 1] = !scoreData
                        .getEachHoleLocked()[scoreData.getCurrentHole() - 1];
                onSaveResult(scoreData);
                refreshEditor(scoreData, 0);
            }
        });
    }
}